package p32_tomcat如何处理异常;

import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

@Configuration
public class WebConfig {
    //web开发三件套必备
    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
        return new TomcatServletWebServerFactory(9999);
    }

    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }

    @Bean
    public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
        DispatcherServletRegistrationBean bean = new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        bean.setLoadOnStartup(1);
        return bean;
    }

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new RequestMappingHandlerMapping();
    }

    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter requestMappingHandlerAdapter = new RequestMappingHandlerAdapter();
        requestMappingHandlerAdapter.setMessageConverters(List.of(new MappingJackson2HttpMessageConverter()));
        return requestMappingHandlerAdapter;
    }

    @Controller
    public static class MyController {
        @GetMapping("/hello")
        public String hello() {
            int i = 1 / 0;
            return null;
        }

        @GetMapping("/error")
        @ResponseBody
        public Map<String, Object> error(HttpServletRequest request) {
            Exception ex = (Exception)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
            return Map.of("error", ex.getMessage());
        }
    }

    /**
     * 下面定制了tomcat的异常处理行为
     */
    //这个bean可以修改tomcat的默认异常处理行为
    @Bean
    public ErrorPageRegistrar errorPageRegistrar() {
        //这里的参数就是ServletWebServerFactory
        return servletWebServerFactory -> {
            //修改tomcat的错误处理路径，可能是静态页面，也可能是接口。出现错误，以请求转发形式跳转到指定路径
            servletWebServerFactory.addErrorPages(new ErrorPage("/error"));
        };
    }
    //bean后处理器，ServletWebServerFactory初始化前回调，给ServletWebServerFactory注册容器中的ErrorPageRegistrar
    @Bean
    public ErrorPageRegistrarBeanPostProcessor errorPageRegistrarBeanPostProcessor() {
        return new ErrorPageRegistrarBeanPostProcessor();
    }
}
